package com.ae.base.util;

import com.ae.api.IPlaced;
import com.ae.base.ModConfig;
import com.ae.base.ModConstant;
import com.ae.base.PlacedRegister;
import com.ae.base.block.PlacedItem;
import com.ae.base.block.PlacedItemTile;
import com.ae.base.cap.SingleItemStackHandler;
import com.ae.base.register.BlockRegister;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import javax.annotation.Nonnull;
import java.util.Map;

public class PutItemAction {
    public static void put(World world, BlockPos pos, Direction face, ItemStack stack, Direction playerDirection, boolean cycled) {
        TileEntity tileEntity = world.getBlockEntity(pos);

        //所在位置方块实体不是PlacedItemTile。
        if (!(tileEntity instanceof PlacedItemTile)) {
            //点击位置为上表面，生成锭方块
            if (face == Direction.UP) {
                if (cycled) {
                    putItemDown(world, pos, stack, playerDirection);
                } else {
                    putItemDown(world, pos.above(), stack, playerDirection);
                }
            }
            return;
        }

        SingleItemStackHandler handler = ((PlacedItemTile) tileEntity).handler;

        //持有的物品与已存储的物品不符，结束。
        if (!handler.isItemValid(stack)) {
            return;
        }

        int spare = handler.getMaxCount() - handler.getStackInSlot().getCount();

        //如果剩余空间不足以放入一个物品则向上一格进行放置尝试。
        if (spare < 1) {
            put(world, pos.above(), Direction.UP, stack, playerDirection, true);
            return;
        }

        //放入方块中。
        putItemIn(stack, (PlacedItemTile) tileEntity);
        playPutSound(world, pos);
    }

    /**
     * @param world 事件发生的世界
     * @param pos   事件发生的坐标
     * @param stack 触发事件发生的物品
     *              生成物品对应的方块，该方法不检测 World, BlockPos, Stack 是否真实有效。
     */
    private static void putItemDown(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull ItemStack stack, Direction direction) {
        //如未给其设置颜色，以普通物品方式放置，否则以锭方块放置
        int color = -1;
        String id = ModConstant.ITEM_PLACED;

        for (Map.Entry<String, IPlaced> entry : PlacedRegister.placedMap.entrySet()) {
            color = entry.getValue().getColor(stack);

            if (color != -1) {
                id = entry.getKey();
                break;
            }
        }

        //配置文件中禁止放置则跳过
        if (color == -1 && !ModConfig.CAN_ALL_PUT.get()) {
            return;
        }

        //不可放置则跳过
        if (!world.getBlockState(pos).is(Blocks.AIR)) {
            return;
        }

        ItemStack stack1 = stack.copy();
        stack1.setCount(1);
        stack.shrink(1);
        BlockState state = BlockRegister.PLACED_ITEM.get().defaultBlockState();
        state = state.setValue(PlacedItem.DIRECTION, direction);
        world.setBlock(pos, state, 1);
        PlacedItemTile tile = (PlacedItemTile) world.getBlockEntity(pos);

        if (tile != null) {
            tile.handler.setStack(stack1);
            tile.setColor(color);
            tile.setId(id);
            world.sendBlockUpdated(tile.getBlockPos(), tile.getBlockState(), tile.getBlockState(), 1);
        }

        playPutSound(world, pos);
    }

    private static void putItemIn(@Nonnull ItemStack stack, @Nonnull PlacedItemTile tile) {
        ItemStack stack1 = stack.split(1);

        if (!tile.handler.insertItem(stack1, false).isEmpty()) {
            stack.setCount(stack.getCount() + 1);
        }
    }

    private static void playPutSound(World world, BlockPos pos) {
        world.playSound(null, pos, SoundEvents.ITEM_FRAME_PLACE, SoundCategory.BLOCKS, 1, 1);
    }
}
